import Ui_MainWindow
from PyQt5.QtCore import QFile, QFileInfo, pyqtSlot, pyqtSignal, QIODevice
from PyQt5 import QtGui, QtWidgets, QtCore
from PyQt5.QtWidgets import QPushButton, QTableWidgetItem, QInputDialog, QLabel
from PyQt5.QtGui import QIcon, QPixmap
from data_set_read import Data_Read
import pandas as pd
import openpyxl as pyx
from libdataanalysis.LinearRegression.linear_regression import LinearRegression
from PlotWindows import PlotWidget

class MainWindows:
    def __init__(self) -> None:
        self.MainWindow = QtWidgets.QMainWindow()
        self.ui = Ui_MainWindow.Ui_MainWindow()
        self.ui.setupUi(self.MainWindow)
        self.window_ui_init()
        self.file_object_init()
        self.head_num = 10
        
    def window_ui_init(self):
        self.MainWindow.setWindowTitle("Data Analysis By Python")
        self.MainWindow.setWindowIcon(QIcon(QPixmap(":/src/image/icon.jpg")))
        self.ui.progressBar_linear_regression.setValue(0)
        self.statusLable = QLabel("准备完成！")
        self.ui.statusbar.addWidget(self.statusLable, 1)
        qss_file = QFile(":/qss/stypesheet.css")
        if qss_file.open(QIODevice.OpenModeFlag.ReadOnly):
            self.MainWindow.setStyleSheet(qss_file.readAll())
        qss_file.close()
        
    def file_object_init(self):
        self.ui.pushButton_filepath.clicked.connect(self.pushButton_filepath_clicked)
        self.ui.pushButton_filepath_clear.clicked.connect(self.pushButton_filepath_clear_clicked)
        self.ui.pushButton_linear_regression.clicked.connect(lambda checked: self.ui.stackedWidget.setCurrentIndex(0))
        self.ui.pushButton_Kmeans.clicked.connect(lambda checked: self.ui.stackedWidget.setCurrentIndex(1))
        self.ui.actionNumber_Head.triggered.connect(self.action_Number_Head_triggered)
        self.ui.pushButton_linear_regression_begin.clicked.connect(self.pushButton_linear_regression_begin_clicked)
        self.ui.pushButton_linear_regression_show.clicked.connect(self.pushButton_linear_regression_show_clicked)
        self.ui.pushButton_linear_regression_save.clicked.connect(self.pushButton_linear_regression_save_clicked)
        
    def pushButton_filepath_clicked(self):
        file_path = QtWidgets.QFileDialog.getOpenFileName(self.MainWindow, "Open File", ".", "All Files(*);;csv Files(*.csv);;Old Excel Files(*.xls);;New Excel Files(*.xlsx)")
        if file_path[0] is None:
            return
        self.file_path = file_path[0]
        info = QFileInfo(file_path[0])
        suffix = info.suffix()
        if suffix == "csv":
            self.data_read = Data_Read(file_path[0], suffix)
            self.ui.lineEdit_filepath.setText(file_path[0])
        elif suffix == "xls" or suffix == "xlsx":
            self.data_read = Data_Read(file_path[0], suffix)
            self.ui.lineEdit_filepath.setText(file_path[0])

        if self.ui.stackedWidget.currentIndex() == 0:
            self.tableWidget_linear_regression_show()

    def tableWidget_linear_regression_show(self):
        self.ui.tableWidget_linear_regression.clear()
        data_file = QFileInfo(self.ui.lineEdit_filepath.text())
        suffix = data_file.suffix()
        if suffix == "csv":
            self.set_csv_headers(data_file.absoluteFilePath())
        elif suffix == "xlsx" or suffix == "xls":
            self.set_excel_headers(data_file.absoluteFilePath())  
            
       
        
    def set_excel_headers(self, file_path):
        wb = pyx.load_workbook(file_path)
        sheet = wb.active
        self.ui.tableWidget_linear_regression.setRowCount(self.head_num)
        self.ui.tableWidget_linear_regression.setColumnCount(sheet.max_column)
        row_count = 0
        if sheet.max_row < self.head_num:
            max_row = sheet.max_row
        else:
            max_row = self.head_num
        for row in sheet.iter_rows(min_row=1, max_row=max_row, max_col=sheet.max_column, values_only=True):
            for col, data in enumerate(row, start=0):
                item = QTableWidgetItem(str(data))
                self.ui.tableWidget_linear_regression.setItem(row_count, col, item)
            row_count += 1     
        wb.close()
        self.statusLable.setText("加载完成！")
    
    def set_csv_headers(self, file_path):
        with open(file_path, "r") as file:
            for i in range(0, self.head_num):
                if i == 0:
                    line = file.readline()
                    line_stripped = line.rstrip()
                    data_list = line_stripped.split(",")
                    self.ui.tableWidget_linear_regression.setRowCount(self.head_num)
                    self.ui.tableWidget_linear_regression.setColumnCount(len(data_list))
                    for j in range(0, len(data_list)):
                        item = QTableWidgetItem(str(data_list[j]))
                        self.ui.tableWidget_linear_regression.setItem(i, j, item)
                else:
                    line = file.readline()
                    line_stripped = line.rstrip()
                    data_list = line_stripped.split(",")
                    for j in range(0, len(data_list)):
                        item = QTableWidgetItem(str(data_list[j]))
                        self.ui.tableWidget_linear_regression.setItem(i, j, item)
        file.close()
        self.statusLable.setText("加载完成！")
 
    def pushButton_filepath_clear_clicked(self):
        self.ui.lineEdit_filepath.clear()
      
    def action_Number_Head_triggered(self):
        nb_head = QtWidgets.QInputDialog.getInt(self.MainWindow, "Head Number", "设置头行数", 10, 1, 20, 1)
        if nb_head[1] == True:
            self.head_num = nb_head[0]
            
    def pushButton_linear_regression_begin_clicked(self):
        if self.ui.lineEdit_linear_regression_original.text is None or self.ui.lineEdit_linear_regression_target is None:
            self.ui.statusbar.s
        info = QFileInfo(self.file_path)
        suffix = info.suffix()
        if suffix == "csv":
            data = pd.read_csv(self.file_path)
        elif suffix == "xls" or suffix == "xlsx":
            data = pd.read_excel(self.file_path)
        train_data = data.sample(frac=self.ui.doubleSpinBox_linear_regression_train_percent.value())
        self.test_data = train_data.drop(train_data.index)
        x = train_data[self.ui.lineEdit_linear_regression_original.text().split(",")].values
        y = train_data[self.ui.lineEdit_linear_regression_target.text()].values
        
        num_iterations = self.ui.spinBox_linear_regression_iter.value()
        learning_rate = self.ui.doubleSpinBox_linear_regression_rate.value()
        polynomial_degress = self.ui.spinBox_linear_regression_ploynmial.value()
        sinusoid_degress = self.ui.spinBox_linear_regression_sinusoid.value()
        normalize_data = True
        
        linear_regression = LinearRegression(x, y, polynomial_degress, sinusoid_degress, normalize_data)
        (theta, cost_history) = linear_regression.train(
            learning_rate,
            num_iterations
        )
        msg = "开始损失: {:.20f},结束损失: {:.20f}".format(cost_history[0], cost_history[-1])
        self.statusLable.setText(msg)
        self.draw_linear_regression_result(num_iterations, cost_history, "num_iterations", "cost_history")
        
    def draw_linear_regression_result(self, num_iterations : int, cost_history : list, xlabel, ylabel):
        num_iter_list = [i for i in range(num_iterations)]
        self.plotwidget = PlotWidget(num_iter_list, cost_history, xlabel, ylabel)
        self.plotwidget.show()
        
    def pushButton_linear_regression_show_clicked(self):
        if self.plotwidget is not None:
            self.plotwidget.show()
            
    def pushButton_linear_regression_save_clicked(self):
        if self.plotwidget is not None:
            dir_path = QtWidgets.QFileDialog.getExistingDirectory(self.MainWindow, "Chose Directory", ".")
            if dir_path is not None:
                self.plotwidget.save(dir_path)
                
    def statusLabel_black(self):
        self.statusLable.setStyleSheet("color:black")
    
    def statusLabel_red(self):
        self.statusLable.setStyleSheet("color:red")